#ifndef AHH_H
#define AHH_H

#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include "./random.h"

#define INF 0x7f7f7f7f

using std::vector;
using std::queue;

class Ann {
protected:
struct Efunction {
    Efunction() {}
    Efunction(float _a, float _k, float _b) : a(_a), k(_k), b(_b) {}
    
    float a, k, b;
    
    inline float calc(int t) {
        return a * exp(-k * t) + b;
    }
};

struct Edge {
	Edge() {}
	Edge(int _from, int _to, float _weight) : from(_from), to(_to), weight(_weight) {}

	int from, to;
	float weight;
};

struct Cell {
    Cell() : category(0),
		voltage(0.0f), temp_voltage(0.0f),
		last_active_time(-INF), last_stimulate_time(-INF), last_deal_time(-INF) {}

	int category; // 0表示内层神经元，-1为输入层，1~N为输出层（编号为输出结果）
    float voltage, temp_voltage;
    int last_active_time; // 上次动作时间戳
	int last_stimulate_time; // 上次刺激时间戳
	int last_deal_time; // 上次处理时间戳

	Efunction threshold; // 阈值函数
	Efunction reduce; //漏电函数
    vector<int> in_edge_ids;
	vector<int> out_edge_ids;

	inline void init() {
		threshold = Efunction(exp(normal()), exp(normal()), exp(normal()));
		reduce = Efunction(exp(normal()), exp(normal()), exp(normal()));
	}

	inline void clearMemory() {
		voltage = temp_voltage = 0.0f;
		last_active_time = last_stimulate_time = last_deal_time = -INF;
	}
};

public:
int time, timeout;

protected:
vector<Edge> edges;
vector<Cell> cells;
vector<int> input_cell_ids;

private:
queue<int> q; // 神经网络运行时所用的队列

protected:
// 构建辅助数组：input_cell_ids，out_edge_ids，in_edge_ids
void buildAssistArr();

private:
// 判断神经元电荷量是否超过阈值
bool isOverThreshold(int x);
// 使神经元发生动作电位
void activeCell(int x);

public:
Ann(int timemout) : time(0), timeout(timemout) {}
Ann(int max_cell_num, int max_edge_num,
	int input_cell_num, int output_cell_num, 
	int timemout);
Ann(const char *filename, int timemout);

void clearMemory();

/* 返回值说明
0：无输出
-1：神经网络达到时间上限
1~N：为输出结果
*/
int run(bool input_data[]);

// 变异
void variateEdge(float rate);
void variateCell(float rate);

void saveParam(const char *filename);

};

#include "ann.cpp"

#endif